// event handler functions //

function popUpMenu(node) {
	var coords = node.cumulativeOffset();
	// Create pop-up menu
	nodeOptions = new Object;
	nodeOptions.nodeMenu = new Element("div",{'class':'nodeOptionsMenu'});
	nodeOptions.newNodeOption = new Element("div");
	nodeOptions.newNodeOption.update("New");
	nodeOptions.newNodeOption.onclick = function () {newNode(node.id,coords)};
	nodeOptions.nodeMenu.insert ({'bottom' : nodeOptions.newNodeOption});
	nodeOptions.editNodeOption = new Element("div");
	nodeOptions.editNodeOption.update("Edit");
	nodeOptions.editNodeOption.onclick = function () {editNode(node.id)};
	nodeOptions.nodeMenu.insert ({'bottom' : nodeOptions.editNodeOption});
	nodeOptions.deleteNodeOption = new Element("div");
	nodeOptions.deleteNodeOption.update("Delete");
	nodeOptions.deleteNodeOption.onclick = function () {deleteNode(node.id)};
	nodeOptions.nodeMenu.insert ({'bottom' : nodeOptions.deleteNodeOption});
	// find coordinates of node
	nodeOptions.nodeMenu.style.top = coords[1] + 'px';
	width = node.getWidth();
	nodeOptions.nodeMenu.style.left = coords[0] + width + 'px';
	// insert into DOM
	var pageBody = $$('body')[0];
	pageBody.insert ({'bottom' : nodeOptions.nodeMenu});
}

function newNodeForm(id,coords) {
	var formContainer = new Element("div",{'class':'newNodeForm'});
	var form = new Element("form",{'action':'','method':'post','name':'newNode','id':'newNode'});
	var textField = new Element("input",{'type':'text','name':'newNodeName','value':''});
	var idField = new Element('input',{'type':'hidden','name':'nodeID','value':id});
	var submit = new Element('input',{'type':'submit','value':'submit','onclick':'submitNewNode();'});
	formContainer.insert ({'bottom' : form});
	form.insert ({'bottom' : textField});
	form.insert ({'bottom' : idField});
	form.insert ({'bottom' : submit});
	formContainer.style.top = coords[1]+"px";
	formContainer.style.left = coords[0]+"px";
	var pageBody = $$('body')[0];
	pageBody.insert ({'bottom' : formContainer});
}

function submitNewNode() {
	var newNodeForm = $('newNode');
	var newNodeData = new Object();
	newNodeData['parentID'] = newNodeForm.nodeID.value;
	newNodeData['newNodeName'] = newNodeForm.newNodeName.value;
	var formContainer = $$('.newNodeForm')[0];
	formContainer.remove();
	alert('Parent ID: '+newNodeData['parentID']+' New node text: '+newNodeData['newNodeName']);
	conlog('Parent ID: '+newNodeData['parentID']+' New node text: '+newNodeData['newNodeName']);
	var d = {}; // TODO enqueue this or update model or something
	d['action'] = 'addchild';
	d['parentID'] = newNodeForm.nodeID.value;
	d['text'] = newNodeForm.newNodeName.value;
	// d['uid'] = wave.getViewer().getId(); // TODO prototype+wave breaks getViewer??
	wave.getState().submitDelta(d);
}

function newNode(id,coords) {
	nodeOptions.nodeMenu.remove();
	newNodeForm(id,coords);
}
function editNode(id) {
	nodeOptions.nodeMenu.remove();
	alert("Edit node"+id);
}

function deleteNode(id) {
	nodeOptions.nodeMenu.remove();
	alert("Delete node"+id);
}

////////////
//
/////////////

var prefs = new gadgets.Prefs();
// TODO can users see gadget prefs stuff somewhere?
var st = null; // the spacetree

/** 
 * CONSTANTS
 */
var KEY_GRAPH = 'mindwave.graph';

var SEP = '_';
 
var KEY_ADDNODE = '.a',
 KEY_ADDCHILD = '.ac';

/**
 * Test data
 */
var testTree = {
	id: "a",
	name: "Node A",
	data: {},
	children: [	{
		id: "b",
		name: "Node B",
		data: {},
		children: []
	},
	{
		id: "c",
		name: "Lorem ipsum dolor sit amet. Sic laren puir necesitat guerdo.",
		data: {},
		children: [	{
			id: "d",
			name: "Node D",
			data: {},
			children: []
		}
		]
	}
	]
};

/** 
 * Initialization
 */
function init() {
	initializeGraph();
	initializeStateHandling();
}

function initializeGraph() {
	var graphdiv = document.getElementById('graph');
	var w = 1000, h = 500; // TODO div.offsetwidth?
	var canvas = new Canvas('mycanvas', {
		'injectInto': 'graph',
		'width': w,
		'height': h,
		'backgroundColor': '#ffffff'
	});

	var graphConfig = {
		duration: 400,         //set duration for the animation
		transition: Trans.Quart.easeInOut,         //set animation transition type
		levelDistance: 50,         //set distance between node and its children
		Node: {
			height: 60,
			width: 150,
			type: 'rectangle',
			color: '#ccc',
			overridable: true
		},
		Edge: {
			type: 'bezier',
			overridable: true
		},
		onCreateLabel: function(label, node){  
         label.id = node.id;              
         label.innerHTML = node.name;  
         label.onclick = function(){
	  		popUpMenu(this);
         }
         //set label styles  
         var style = label.style;  
         style.width = 150 + 'px';         
         style.cursor = 'pointer';  
         style.color = '#000';  
         style.fontSize = '0.8em';  
         style.textAlign= 'center';
         style.fontFamily = "Arial";
         style.padding = "3px";
     }
	};

	st = new ST(canvas, graphConfig);
	
	// load graph from memory
	//var gstring = prefs.getString(KEY_GRAPH);
	var gstring = null;
	if (gstring) {
		// if (wave.getState()) { var gstring = wave.getState().get(KEY_GRAPH); }
		var graph = gadgets.json.parse(gstring);
		conlog("TODO Loading graph from userprefs: " + ostring(graph));
		st.loadJSON(graph); // TODO JIT doesn't like empty graphs {} for some functions
		st.compute();     //compute node positions and layout
		st.onClick(st.root);     //emulate a click on the root node // TODO any issue with empty graph?
	} else { // JIT does not want to try to render a new empty graph {}
		conlog("NEW GADGET. There is no previous graph."); // graph is null
		conlog("Testing with test graph..."); // TODO testing
		st.loadJSON(testTree); // TODO testing with empty graph start
		st.compute();     //compute node positions and layout
		st.onClick(st.root);     //emulate a click on the root node // TODO any issue with empty graph?
	}
}

/* TODO from Jeff -- uses Prototype -- we'll use gadgets.util.onload prolly
Event.observe(window, 'load', function() {
 	init();
});
*/

function initializeStateHandling() {
	if (wave && wave.isInWaveContainer()) {
		wave.setStateCallback(stateUpdated);
	}
}

function saveGraph() {
	if (st && st.root) { // TODO test/doc id must not be false in logical context
		var gstring = gadgets.json.stringify(st.json); // TODO NOW testing this
		conlog("TODO Saving graph. Graph: " + gstring); // TODO do it
		//prefs.set(KEY_GRAPH, gstring);
	} else { // graph should be null
		conlog("There is no graph to save.");
		//prefs.set(KEY_GRAPH, null); // TODO does this ensure clear memory for gadget's graph?
	}
}

/**
 * Event and data management
 */
function stateUpdated() {
	conlog("State callback triggered.");
	printState();
	//wave.getState().submitDelta({'addnodeyo': null}); // API says delete key by submit null value
	/* I expected my delta to become a key, value pair in state. It doesn't seem to be happening. 
	 * So I'm working around that.
	  for (var key in wave.getState().getKeys()) {
		var value = wave.getState().get(key);
		conlog("State key: " + key + " value: " + value);
		var d = {};
		d[key] = null;
		wave.getState().submitDelta(d); // API says delete key by submit null value -- pffft this triggers another state update!
	   }
	 */
	var action = wave.getState().get('action'); 
	if (action) {
		conlog("Got action: " + action);
		conlog(wave.getState().get('uid') + " : " + wave.getState().get('text'));
	}
	saveGraph();
}

function buttonClicked() {
	conlog("BUTTON CLICKED."); // TODO button dev
	//if (wave.getViewer()) { // i seen this return null == laggy bug?
	//var vid = wave.getViewer().getId(); // get viewer ID/Name
	var d = {};
	d['test'] = 'testy';
	//d[KEY_ADDNODE + SEP + vid] = vid; // TODO finish
	conlog("Submitting delta: " + ostring(d) + "...");
	wave.getState().submitDelta(d);  // TODO state not being triggered
	conlog("...Delta submitted.");
}


gadgets.util.registerOnLoadHandler(init); //window.addEventListener("load", init, false);

/***************
 * DEBUGGING AND UTILITY
 * TODO remove some of this debugging and utility stuff
 *
 */
 
 /// TODO remove this UTIL section
var debug = true;

function conlog(msg) {
	if (debug) {
		console.log(msg);
	}
}

function printState() {
	if (debug) {
		console.log("GADGET ENV AND STATE -------------------------");
		console.log("Viewer: " + wave.getViewer().getDisplayName() + " ID:" + wave.getViewer().getId());
		console.log("Gadget State: ")
		console.log(wave.State.toString());		
	}
}

function ostring(a) { // FEH what's the one-liner for this?
	var s = "";
	for (var x in a) {
	    s += x + ": " + a[x] + ", ";
	}
	return s;
}

 /// DEBUG: Quickies
function testButtonClicked() { // TODO remove this debugging callback
	conlog("testButtonClicked(): submitting a simple delta");
	var value = parseInt(wave.getState().get('count', '0'));
	wave.getState().submitDelta({
		'count': value + 1
		});
}
